﻿using System;
using System.Linq;
using System.Linq.Expressions;

namespace IDI.Studio.Core
{
    public static class ExpressionExtensions
    {
        private static Expression<T> Compose<T>(this Expression<T> one, Expression<T> other, Func<Expression, Expression, Expression> merge)
        {
            var parameters = one.Parameters.Select((f, i) => new { f, s = other.Parameters[i] }).ToDictionary(p => p.s, p => p.f);

            var otherBody = ParameterReplacer.ReplaceParameters(parameters, other.Body);

            return Expression.Lambda<T>(merge(one.Body, otherBody), one.Parameters);
        }

        public static Expression<Func<T, bool>> And<T>(this Expression<Func<T, bool>> one, Expression<Func<T, bool>> other)
        {
            return one.Compose(other, Expression.And);
        }

        public static Expression<Func<T, bool>> Or<T>(this Expression<Func<T, bool>> one, Expression<Func<T, bool>> other)
        {
            return one.Compose(other, Expression.Or);
        }
    }
}
